from django.db import transaction
from django.shortcuts import render
from rest_framework import status
from rest_framework.decorators import action
from rest_framework.mixins import ListModelMixin
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework.viewsets import ModelViewSet
from apps.spit.serializers import SpitModelSerializer
from apps.spit.models import Spit
from django_redis import get_redis_connection


# Create your views here.

# class SpitViewSet(ModelViewSet):
#     permission_classes = []
#     serializer_class = SpitModelSerializer
#     queryset = Spit.objects.filter(parent=None).orderby('-publishtime')
#     # spitList = self.get_queryset().filter(parent=pk).order_by("-publishtime")
#     '''
#     方法指南(DRF文档)：
#         可将@action装饰器用于点赞/取消点赞和收藏/取消收藏中
#         如果您具有可路由的临时方法，则可以使用@action装饰器将它们标记为可路由的。
#         像常规操作一样，额外的操作可能打算用于单个对象或整个集合。
#         为了表明这一点，请将detail参数设置为True或False。
#         路由器将相应地配置其URL模式。例如，DefaultRouter将配置详细信息操作以包含pk在其URL模式中。
#         在action装饰后，系统会GET默认请求，也可以接受设定其他HTTP方法methods的参数。
#         装饰器允许您覆盖任何视图集中级别的配置，例如permission_classes，serializer_class，filter_backends.
#     '''
#
#     def perform_authentication(self, request):
#         pass
#     def list(self, request, *args, **kwargs):
#         spits = self.queryset.all()
#         user = self.request.user
#         #判断是否是登陆用户，登陆用户显示是否点赞收藏
#         if user.is_anonymous:
#             serializer = self.get_serializer(spits,many=True)
#             return Response(serializer.data)
#         else:
#             redis_conn = get_redis_connection('spit')
#
#
#
#
#     # 新增吐槽/吐槽评论，重写mixin的create方法
#     def create(self, request, *args, **kwargs):
#         # 如果是新增吐槽，则parent=null
#         # 判断是否是吐槽
#         if request.data.get('parent'):
#             # 评论吐槽
#             if request.user.is_anonymous:
#                 return Response({
#                     'message': '请您登录后操作',
#                     'success': False
#                 })
#             request.data['userid'] = request.user.id
#             # 重写部分Mixin的create方法
#             serializer = self.get_serializer(data=request.data)
#             serializer.is_valid(raise_exception=True)
#             # 事务存储
#             with transaction.atomic():
#                 # 保存点
#                 savepoint = transaction.savepoint()
#                 self.perform_create(serializer)
#                 spit = Spit.objects.get(id=request.data.get('parent'))
#                 spit.comment += 1
#                 spit.save()
#                 transaction.savepoint_commit(savepoint)
#             headers = self.get_success_headers(serializer.data)
#             return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
#
#         serializer = self.get_serializer(data=request.data)
#         serializer.is_valid(raise_exception=True)
#         self.perform_create(serializer)
#         headers = self.get_success_headers(serializer.data)
#         return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
#
#     def retrieve(self, request, *args, **kwargs):
#         '''吐槽详情'''
#
#         pk = self.kwargs.get('pk')
#         spit = Spit.objects.get(id=pk)
#         spit.visits += 1
#         spit.save()
#         instance = self.get_object()
#         serializer = self.get_serializer(instance)
#         return Response(serializer.data)
#
#     #
#     @action(methods=['get'], detail=True)
#     def children(self, request, pk):
#         # get,请求url=/spit/{id}/children
#         spits = Spit.objects.filter(parent=pk)
#         serializer = self.get_serializer(instance=spits, many=True)
#         return Response(serializer.data)
#
#     @action(methods=['put'], detail=True)
#     def updatethumbup(self, request, pk):
#         if request.user.is_anonymous:
#             return Response({
#                 'message': '请您登录后操作',
#                 'success': False
#             })
#         user = request.user
#         spit = Spit.objects.get(id=pk)
#         redis_conn = get_redis_connection('spit')
#         # 从redis查出当前用户点赞记录
#         spit_thumbup = redis_conn.hkeys(f'thumbup_{user.id}')
#         spit_thumbup = [spit.decode() for spit in spit_thumbup]
#
#         if pk in spit_thumbup:
#             redis_conn.hdel(f'thumbup_{user.id}', pk)
#             spit.thumbup -= 1
#             spit.save()
#             return Response({"message": "取消点赞成功", "success": True})
#         else:
#             redis_conn.hset(f'thumbup_{user.id}', pk, 1)
#             spit.thumbup += 1
#             spit.save()
#             return Response({"message": "点赞成功", "success": True})
        
class SpitViewSet(ModelViewSet):

    queryset = Spit.objects.all()
    # queryset = Spit.objects.filter(parent=None).orderby('-publishtime')
    serializer_class = SpitModelSerializer

    def perform_authentication(self, request):
        pass

    #吐槽列表
    def list(self, request, *args, **kwargs):
        spits = self.queryset.filter(parent=None).order_by('-publishtime').all()

        sptList = []
        try:
            #未登录设置user=None
            user = self.request.user
        except Exception:
            user = None
        if user is not None and user.is_authenticated:
            redis_conn = get_redis_connection('spit')
            for spit in spits:
                setcollect = redis_conn.hget(f'collect_{user.id}', str(spit.id))
                setthumbup = redis_conn.hget(f'thumbup_{user.id}', str(spit.id))
                if setcollect:
                    spit.collected = True
                if setthumbup:
                    spit.hasthumbup = True
                sptList.append(spit)
        else:
            sptList = spits

        serializer = self.get_serializer(sptList, many=True)
        return Response(serializer.data)

    # 新增吐槽/吐槽评论，重写mixin的create方法
    def create(self, request, *args, **kwargs):
        # 如果是新增吐槽，则parent=null
        # 判断是否是吐槽
        if request.data.get('parent'):
            # 评论吐槽
            if request.user.is_anonymous:
                return Response({
                    'message': '请登陆',
                    'success': False
                })
            request.data['userid'] = request.user.id
            # 重写部分Mixin的create方法
            serializer = self.get_serializer(data=request.data)
            serializer.is_valid(raise_exception=True)
            # 事务存储
            with transaction.atomic():
                # 保存点
                savepoint = transaction.savepoint()
                self.perform_create(serializer)
                spit = Spit.objects.get(id=request.data.get('parent'))
                spit.comment += 1
                spit.save()
                transaction.savepoint_commit(savepoint)
            headers = self.get_success_headers(serializer.data)
            return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)




    # 吐槽详情
    def retrieve(self, request, *args, **kwargs):
        spit = self.get_object()
        spit.visits += 1
        spit.save()
        user = self.request.user
        if user is not None and user.is_authenticated:
            redis_conn = get_redis_connection('spit')
            setcollect = redis_conn.hget(f'collect_{user.id}', kwargs.get("pk"))
            setthumbup = redis_conn.hget(f'thumbup_{user.id}', kwargs.get("pk"))
            if setcollect:
                spit.collected = True
            if setthumbup:
                spit.hasthumbup = True
        serializer = self.get_serializer(instance=spit)
        return Response(serializer.data)

    # 获取吐槽的评论
    @action(methods=["GET"], detail=True)
    def children(self, request, pk):
        spitList = self.get_queryset().filter(parent=pk).order_by("-publishtime")

        sptList = []
        try:
            user = self.request.user
        except Exception:
            user = None
        if user is not None and user.is_authenticated:
            redis_conn = get_redis_connection('spit')
            for spit in spitList:
                setcollect = redis_conn.hget(f'collect_{user.id}', str(spit.id))
                setthumbup = redis_conn.hget(f'thumbup_{user.id}', str(spit.id))
                if setcollect:
                    spit.collected = True
                if setthumbup:
                    spit.hasthumbup = True
                sptList.append(spit)
        else:
            sptList = spitList

        serializer = self.get_serializer(instance=sptList, many=True)
        return Response(serializer.data)
    # 收藏或取消
    @action(methods=['put'], detail=True)
    def collect(self,request,pk):
        spitlist=[]
        user = self.request.user
        spit = self.get_object()

        if user.is_anonymous:
            return Response({'message': '请登陆'}, status=status.HTTP_401_UNAUTHORIZED)
        redis_conn = get_redis_connection('spit')
        spit_collected = redis_conn.hkeys(f'collect_{user.id}')
        for spits in spit_collected:
            spitlist.append(spits.decode())


        if pk in spitlist:
            redis_conn.hdel(f'collect_{user.id}', pk)
            spit.save()
            return Response({"message": "取消收藏成功", "success": True})
        else:
            redis_conn.hset(f'collect_{user.id}', pk, 1)
            spit.save()
            return Response({"message": "收藏成功", "success": True})

    # 点赞或取消
    @action(methods=['put'], detail=True)
    def updatethumbup(self, request, pk):
        spitlist=[]
        user = request.user
        spit = Spit.objects.get(id=pk)
        #判断是否匿名
        if user.is_anonymous:
            return Response({'message': '请登陆', "success": False}, status=status.HTTP_401_UNAUTHORIZED)
        user = request.user
        spit = Spit.objects.get(id=pk)
        if not user.is_authenticated:
            return Response({'message': '请登陆', "success": False}, status=status.HTTP_401_UNAUTHORIZED)
        redis_conn = get_redis_connection('spit')
        #根据id查询用户点赞记录
        spit_thumbup = redis_conn.hkeys(f'thumbup_{user.id}')
        for spits in spit_thumbup:
            spitlist.append(spits.decode())

        if pk in spitlist:
            redis_conn.hdel(f'thumbup_{user.id}', pk)
            spit.thumbup -= 1
            spit.save()
            return Response({"message": "取消点赞成功", "success": True})
        else:
            redis_conn.hset(f'thumbup_{user.id}', pk, 1)
            spit.thumbup += 1
            spit.save()
            return Response({"message": "点赞成功", "success": True})